package cn.omisheep.au.core;


import cn.omisheep.au.UserContext;
import io.jsonwebtoken.*;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 * @author zhou xin chen  😊
 * 联系方式 qq:1269670415  email:xinchenzhou666@gmail.com
 */
public class JwtHelper {


    private final Long ttl; // 存活时间,单位 ms
    private final JwtBuilder builder;
    private final JwtParser parser;

    public JwtHelper(AuConfig config) {
        this.ttl = AuUtil.parseTimeValue(config.getJwtConfig().getTtl());
        String key = config.getJwtConfig().getKey();
        this.builder = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, key);
        this.parser = Jwts.parser().setSigningKey(key);
    }

    /**
     * 根据userContext生成token
     *
     * @param userContext 用户
     * @return jwt
     */
    public String createToken(UserContext userContext) {
        Claims claims = generateClaims(userContext);
        String tokenId = UUID.randomUUID().toString();
        return createTokenMeta(claims, tokenId);
    }


    public Claims parseToken(String token){
        return parser.parseClaimsJws(token).getBody();
    }


    //   ====  ==== ==== === ===
    private Claims generateClaims(UserContext userContext) {

        String username = userContext.getUsername();
        if (null == username || username.trim().equals(""))
            throw new IllegalArgumentException("用户名为空无法创建jwt token");

        // 设置token里的数据
        Claims claims = Jwts.claims().setSubject(username);
        claims.put("userId", userContext.getId());
        claims.put("role", userContext.getRole());

        Map<String, Object> customProperties = userContext.auCustomPropertiesInToken();
        if (null != customProperties) {
            customProperties.forEach((key, value) -> {
                if (claims.containsKey(key)) {
                    throw new IllegalArgumentException(String.format("token payload已包含属性'%s'", key));
                } else {
                    claims.put(key, value);
                }
            });
        }

        return claims;
    }

    /**
     * 设置jwt自有的几个payload如签发者、有效期等 并生成token
     *
     * @param claims  信息
     * @param tokenId tokenId
     * @return 返回token
     */
    private String createTokenMeta(Claims claims, String tokenId) {
        LocalDateTime currentTime = LocalDateTime.now();
        long exp = System.currentTimeMillis() + ttl; // 失效时间

        return builder
                .setClaims(claims) // 设置cliams
                .setId(tokenId) // 设置tokenId
                .setIssuer("zxc") // 发行用户
                .setIssuedAt(Date.from(currentTime.atZone(ZoneId.systemDefault()).toInstant())) // 发行时间
                .setExpiration(new Date(exp))
                .compact();
    }
}
